package com.service.impl;

import com.dao.ProductMapper;
import com.entity.Product;
import com.entity.ProductEs;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.service.ProductService;
import com.service.RedisService;
import config.MqConfig;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class ProductServiceImpl implements ProductService {
    public static final String[] ES_SEARCH_FIELDS = {"name", "productDesc"};
    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisService redisService;
    @Override
    public void insert(Product product) {
        productMapper.insert(product);
        rabbitTemplate.convertAndSend(MqConfig.ES_MQ_DEMO,product);
    }


    @Override
    public Product getById(int id) {
        Product product = null;
        Object cachedProduct = redisService.get("product:" + id);
        if(cachedProduct!=null){
            System.out.println("=====从缓存中取得数据=====");
            product = (Product) cachedProduct;
            return product;
        }else {
            System.out.println("====从缓存中娶不到数据=== 从db中取");
            product = productMapper.getById(id);
            redisService.setEx("product:" + id,product,30);
        }
        return product;
    }
    @Override
    public List<ProductEs> searchProductsByEs(String keyword) {
        List<ProductEs> result = new ArrayList<>();


        try (RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
                new HttpHost("localhost", 9200, "http")))) {
            SearchRequest request = new SearchRequest(MqConfig.ES_MQ_DEMO);
            //通过HighlightUtils构建HighlightBuilder对象
            HighlightBuilder highlightBuilder = createHighlightBuilder(ES_SEARCH_FIELDS);
            //创建SearchSourceBuilder，并将highlightBuilder设置到SearchSourceBuilder中
            SearchSourceBuilder builder = new SearchSourceBuilder();
            //将highlightBuilder设置到SearchSourceBuilder中
            builder.highlighter(highlightBuilder);
            builder.query(QueryBuilders.multiMatchQuery(keyword, ES_SEARCH_FIELDS));
            request.source(builder);
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            SearchHits sh = response.getHits();
            for (SearchHit hit : sh.getHits()) {
                String sourceAsString = hit.getSourceAsString();
                ProductEs productEs = parseEsData(sourceAsString);
                //处理高亮数据显示问题
                handlerHightligth(hit, productEs);
                result.add(productEs);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    private void handlerHightligth(SearchHit hit, ProductEs productEs) {
        //从命中的记录中获取⾼亮字段的Map集合
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        //循环map获取⾼亮字段信息
        for (String key : highlightFields.keySet()) {
            String highlightValue = highlightFields.get(key).fragments()[0].string();
            //System.out.println(highlightValue);
            if ("name".equalsIgnoreCase(key)) {
                productEs.setName(highlightValue);
            } else if ("productDesc".equalsIgnoreCase(key)) {
                productEs.setProductDesc(highlightValue);
            }
        }
    }

    private static HighlightBuilder createHighlightBuilder(String... fields) {
        //创建⼀个HighlightBuilder
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        for (String field : fields) {
            //指定需要⾼亮显示的字段
            HighlightBuilder.Field highlightField = new HighlightBuilder.Field(field);
            //设置⾼亮的类型， unified为荧光笔
            highlightField.highlighterType("unified");
            //将⾼亮字段（highlightField）添加到highlightBuilder中
            highlightBuilder.field(highlightField);
            //设置高亮的前缀与后缀，默认是<em>与</em>
            highlightBuilder.preTags("<span class='hl'>");
            highlightBuilder.postTags("</span>");
        }
        return highlightBuilder;
    }

    /**
     * 可以在配置类中配置一个全局用的ObjectMapper，
     * 这里是为了方便就直接实例化一个进行反序列化操作
     * @param data
     * @return
     */
    private ProductEs parseEsData(String data){
        ObjectMapper objectMapper = new ObjectMapper();
        ProductEs productEs = null;
        try {
            productEs = objectMapper.readValue(data, ProductEs.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return productEs;
    }
}
